﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Xml.Serialization;
using ElectronicCommerce.Framework.ServiceModel.WCF.BindingMessage;

namespace ElectronicCommerce.Framework.ServiceModel.WCF.TransferElement
{
    public class NetTcpBindingHandler : IGetBindingByConfig
    {
        #region IGetBindingByConfig Members

        public System.ServiceModel.Channels.Binding GetBindingMsgByConfig(string configStr)
        {
            if (string.IsNullOrEmpty(configStr))
                return new NetTcpBinding();
            else
            {
                XmlSerializer serial = new XmlSerializer(typeof(NetTcpBindingMsg));
                NetTcpBindingMsg bindingMsg = (NetTcpBindingMsg)serial.Deserialize(new StringReader(configStr));
                return GetBindingFromMsg(bindingMsg);
            }
        }

        #endregion

        private NetTcpBinding GetBindingFromMsg(NetTcpBindingMsg bindingMsg)
        {
            NetTcpBinding binding = new NetTcpBinding();
            if (bindingMsg.name != null)
            {
                binding.Name = bindingMsg.name;
            }
            if (bindingMsg.closeTimeout != null)
            {
                binding.CloseTimeout = TimeSpan.Parse(bindingMsg.closeTimeout);
            }

            binding.ListenBacklog = bindingMsg.listenBacklog;
            binding.MaxBufferSize = bindingMsg.maxBufferSize;
            binding.MaxConnections = bindingMsg.maxConnections;
            binding.PortSharingEnabled = bindingMsg.portSharingEnabled;

            binding.HostNameComparisonMode = (HostNameComparisonMode)bindingMsg.hostNameComparisonMode;
            binding.MaxBufferPoolSize = bindingMsg.maxBufferPoolSize;
            binding.MaxReceivedMessageSize = bindingMsg.maxReceivedMessageSize;

            if (bindingMsg.openTimeout != null)
            {
                binding.OpenTimeout = TimeSpan.Parse(bindingMsg.openTimeout);
            }
            if (bindingMsg.receiveTimeout != null)
            {
                binding.ReceiveTimeout = TimeSpan.Parse(bindingMsg.receiveTimeout);
            }
            if (bindingMsg.sendTimeout != null)
            {
                binding.SendTimeout = TimeSpan.Parse(bindingMsg.sendTimeout);
            }
            binding.TransactionFlow = bindingMsg.transactionFlow;
            binding.TransactionProtocol = GetTransactionProtocol(bindingMsg.transactionProtocol);
            binding.TransferMode = (TransferMode)bindingMsg.transferMode;

            if (bindingMsg.reliableSession != null)
            {
                binding.ReliableSession.Enabled = bindingMsg.reliableSession.enabled;
                if (bindingMsg.reliableSession.inactivityTimeout != null)
                {
                    binding.ReliableSession.InactivityTimeout = TimeSpan.Parse(bindingMsg.reliableSession.inactivityTimeout);
                }
                binding.ReliableSession.Ordered = bindingMsg.reliableSession.ordered;
            }

            if (bindingMsg.readerQuotas != null)
            {
                binding.ReaderQuotas.MaxArrayLength = bindingMsg.readerQuotas.maxArrayLength;
                binding.ReaderQuotas.MaxBytesPerRead = bindingMsg.readerQuotas.maxBytesPerRead;
                binding.ReaderQuotas.MaxDepth = bindingMsg.readerQuotas.maxDepth;
                binding.ReaderQuotas.MaxNameTableCharCount = bindingMsg.readerQuotas.maxNameTableCharCount;
                binding.ReaderQuotas.MaxStringContentLength = bindingMsg.readerQuotas.maxStringContentLength;
            }

            if (bindingMsg.security != null)
            {
                TranNetTcpSecurity(bindingMsg, binding);
            }

            return binding;
        }

        private TransactionProtocol GetTransactionProtocol(string transactionProtocol)
        {
            switch (transactionProtocol)
            {
                case "OleTransactions":
                    return TransactionProtocol.OleTransactions;

                //case "WSAtomicTransaction11":
                //    return TransactionProtocol.WSAtomicTransaction11;

                case "WSAtomicTransactionOctober2004":
                    return TransactionProtocol.WSAtomicTransactionOctober2004;

                default:
                    return TransactionProtocol.Default;
            }
        }

        private void TranNetTcpSecurity(NetTcpBindingMsg bindingMsg, NetTcpBinding binding)
        {
            switch (bindingMsg.security.mode)
            {
                case NetTcpBindingMsgSecurityMode.None:
                    binding.Security.Mode = SecurityMode.None;
                    break;
                case NetTcpBindingMsgSecurityMode.Message:
                    binding.Security.Mode = SecurityMode.Message;
                    if (bindingMsg.security.message.algorithmSuite != null)
                    {
                        binding.Security.Message.AlgorithmSuite = (System.ServiceModel.Security.SecurityAlgorithmSuite)Convert.ChangeType(bindingMsg.security.message.algorithmSuite, typeof(System.ServiceModel.Security.SecurityAlgorithmSuite));
                    }
                    binding.Security.Message.ClientCredentialType = (MessageCredentialType)bindingMsg.security.message.clientCredentialType;
                    break;
                case NetTcpBindingMsgSecurityMode.Transport:
                    binding.Security.Mode = SecurityMode.Transport;
                    binding.Security.Transport.ClientCredentialType = (TcpClientCredentialType)bindingMsg.security.transport.clientCredentialType;
                    binding.Security.Transport.ProtectionLevel = (System.Net.Security.ProtectionLevel)bindingMsg.security.transport.protectionLevel;
                    break;
                case NetTcpBindingMsgSecurityMode.TransportWithMessageCredential:
                    binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
                    if (bindingMsg.security.message.algorithmSuite != null)
                    {
                        binding.Security.Message.AlgorithmSuite = (System.ServiceModel.Security.SecurityAlgorithmSuite)Convert.ChangeType(bindingMsg.security.message.algorithmSuite, typeof(System.ServiceModel.Security.SecurityAlgorithmSuite));
                    }
                    binding.Security.Message.ClientCredentialType = (MessageCredentialType)bindingMsg.security.message.clientCredentialType;
                    binding.Security.Transport.ClientCredentialType = (TcpClientCredentialType)bindingMsg.security.transport.clientCredentialType;
                    binding.Security.Transport.ProtectionLevel = (System.Net.Security.ProtectionLevel)bindingMsg.security.transport.protectionLevel;
                    break;
                default:
                    binding.Security.Mode = SecurityMode.None;
                    break;
            }
        }



        #region IGetBindingByConfig Members


        public string GetAddress(string templateAddress)
        {
            return String.Format("net.tcp://{0}", templateAddress);
        }

        #endregion
    }
}
